home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_195 / microemacs / src.zoo / region.c < prev    next >
C/C++ Source or Header  |  1989-03-23  |  13KB  |  423 lines

  1. /*
  2.  * The routines in this file
  3.  * deal with the region, that magic space
  4.  * between "." and mark. Some functions are
  5.  * commands. Some functions are just for
  6.  * internal use.
  7.  */
  8. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include    "etype.h"
  11. #include        "edef.h"
  12. #include    "elang.h"
  13.  
  14. /*    reglines:    how many lines in the current region
  15.             used by the trim/entab/detab-region commands
  16. */
  17.  
  18. int PASCAL NEAR reglines()
  19.  
  20. {
  21.         register LINE *linep;    /* position while scanning */
  22.     register int n;        /* number of lines in this current region */
  23.         REGION region;
  24.  
  25.     /* check for a valid region first */
  26.         if (getregion(®ion) != TRUE)
  27.                 return(0);
  28.  
  29.     /* start at the top of the region.... */
  30.         linep = region.r_linep;
  31.     region.r_size += region.r_offset;
  32.         n = 0;
  33.  
  34.         /* scan the region... counting lines */
  35.         while (region.r_size > 0L) {
  36.         region.r_size -= llength(linep) + 1;
  37.         linep = lforw(linep);
  38.         n++;
  39.     }
  40.  
  41.     /* place us at the beginning of the region */
  42.         curwp->w_dotp = region.r_linep;
  43.         curwp->w_doto = region.r_offset;
  44.  
  45.         return(n);
  46. }
  47.  
  48. /*
  49.  * Kill the region. Ask "getregion"
  50.  * to figure out the bounds of the region.
  51.  * Move "." to the start, and kill the characters.
  52.  * Bound to "C-W".
  53.  */
  54. PASCAL NEAR killregion(f, n)
  55.  
  56. {
  57.         register int    s;
  58.         REGION          region;
  59.  
  60.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  61.         return(rdonly());    /* we are in read only mode    */
  62.         if ((s=getregion(®ion)) != TRUE)
  63.                 return(s);
  64.         if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
  65.                 kdelete();                      /* command, so do magic */
  66.         thisflag |= CFKILL;                     /* kill buffer stuff.   */
  67.         curwp->w_dotp = region.r_linep;
  68.         curwp->w_doto = region.r_offset;
  69.         return(ldelete(region.r_size, TRUE));
  70. }
  71.  
  72. /*
  73.  * Copy all of the characters in the
  74.  * region to the kill buffer. Don't move dot
  75.  * at all. This is a bit like a kill region followed
  76.  * by a yank. Bound to "M-W".
  77.  */
  78. PASCAL NEAR copyregion(f, n)
  79. {
  80.         register LINE   *linep;
  81.         register int    loffs;
  82.         register int    s;
  83.         REGION          region;
  84.  
  85.         if ((s=getregion(®ion)) != TRUE)
  86.                 return(s);
  87.         if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
  88.                 kdelete();
  89.         thisflag |= CFKILL;
  90.         linep = region.r_linep;                 /* Current line.        */
  91.         loffs = region.r_offset;                /* Current offset.      */
  92.         while (region.r_size--) {
  93.                 if (loffs == llength(linep)) {  /* End of line.         */
  94.                         if ((s=kinsert('\r')) != TRUE)
  95.                                 return(s);
  96.                         linep = lforw(linep);
  97.                         loffs = 0;
  98.                 } else {                        /* Middle of line.      */
  99.                         if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
  100.                                 return(s);
  101.                         ++loffs;
  102.                 }
  103.         }
  104.     mlwrite(TEXT70);
  105. /*              "[region copied]" */
  106.         return(TRUE);
  107. }
  108.  
  109. /*
  110.  * Lower case region. Zap all of the upper
  111.  * case characters in the region to lower case. Use
  112.  * the region code to set the limits. Scan the buffer,
  113.  * doing the changes. Call "lchange" to ensure that
  114.  * redisplay is done in all buffers. Bound to
  115.  * "C-X C-L".
  116.  */
  117. PASCAL NEAR lowerregion(f, n)
  118. {
  119.         register LINE   *linep;
  120.         register int    loffs;
  121.         register int    s;
  122.         int c;
  123.         REGION          region;
  124.  
  125.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  126.         return(rdonly());    /* we are in read only mode    */
  127.         if ((s=getregion(®ion)) != TRUE)
  128.                 return(s);
  129.         lchange(WFHARD);
  130.         linep = region.r_linep;
  131.         loffs = region.r_offset;
  132.         while (region.r_size--) {
  133.                 if (loffs == llength(linep)) {
  134.                         linep = lforw(linep);
  135.                         loffs = 0;
  136.                 } else {
  137.                         c = lgetc(linep, loffs);
  138.             c = lowerc(c);
  139.                         lputc(linep, loffs, c);
  140.                         ++loffs;
  141.                 }
  142.         }
  143.         return(TRUE);
  144. }
  145.  
  146. /*
  147.  * Upper case region. Zap all of the lower
  148.  * case characters in the region to upper case. Use
  149.  * the region code to set the limits. Scan the buffer,
  150.  * doing the changes. Call "lchange" to ensure that
  151.  * redisplay is done in all buffers. Bound to
  152.  * "C-X C-L".
  153.  */
  154. PASCAL NEAR upperregion(f, n)
  155. {
  156.         register LINE   *linep;
  157.         register int    loffs;
  158.         register int    s;
  159.         int c;
  160.         REGION          region;
  161.  
  162.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  163.         return(rdonly());    /* we are in read only mode    */
  164.         if ((s=getregion(®ion)) != TRUE)
  165.                 return(s);
  166.         lchange(WFHARD);
  167.         linep = region.r_linep;
  168.         loffs = region.r_offset;
  169.         while (region.r_size--) {
  170.                 if (loffs == llength(linep)) {
  171.                         linep = lforw(linep);
  172.                         loffs = 0;
  173.                 } else {
  174.                         c = lgetc(linep, loffs);
  175.             c = upperc(c);
  176.                         lputc(linep, loffs, c);
  177.                         ++loffs;
  178.                 }
  179.         }
  180.         return(TRUE);
  181. }
  182.  
  183. /*    Narrow-to-region (^X-<) makes all but the current region in
  184.     the current buffer invisable and unchangable
  185. */
  186.  
  187. PASCAL NEAR narrow(f, n)
  188.  
  189. {
  190.         register int status;    /* return status */
  191.     BUFFER *bp;        /* buffer being narrowed */
  192.     WINDOW *wp;        /* windows to fix up pointers in as well */
  193.     REGION creg;        /* region boundry structure */
  194.     int cmark;        /* current mark */
  195.  
  196.     /* find the proper buffer and make sure we aren't already narrow */
  197.     bp = curwp->w_bufp;        /* find the right buffer */
  198.     if (bp->b_flag&BFNAROW) {
  199.         mlwrite(TEXT71);
  200. /*                      "%%This buffer is already narrowed" */
  201.         return(FALSE);
  202.     }
  203.  
  204.     /* find the boundries of the current region */
  205.         if ((status=getregion(&creg)) != TRUE)
  206.                 return(status);
  207.         curwp->w_dotp = creg.r_linep;    /* only by full lines please! */
  208.         curwp->w_doto = 0;
  209.     creg.r_size += (long)creg.r_offset;
  210.     if (creg.r_size <= (long)curwp->w_dotp->l_used) {
  211.         mlwrite(TEXT72);
  212. /*                      "%%Must narrow at least 1 full line" */
  213.         return(FALSE);
  214.     }
  215.  
  216.     /* archive the top fragment */
  217.     if (bp->b_linep->l_fp != creg.r_linep) {
  218.         bp->b_topline = bp->b_linep->l_fp;
  219.         creg.r_linep->l_bp->l_fp = (LINE *)NULL;
  220.         bp->b_linep->l_fp = creg.r_linep;
  221.         creg.r_linep->l_bp = bp->b_linep;
  222.     }
  223.  
  224.     /* move forward to the end of this region
  225.        (a long number of bytes perhaps) */
  226.     while (creg.r_size > (long)32000) {
  227.         forwchar(TRUE, 32000);
  228.         creg.r_size -= (long)32000;
  229.     }
  230.     forwchar(TRUE, (int)creg.r_size);
  231.     curwp->w_doto = 0;        /* only full lines! */
  232.  
  233.     /* archive the bottom fragment */
  234.     if (bp->b_linep != curwp->w_dotp) {
  235.         bp->b_botline = curwp->w_dotp;
  236.         bp->b_botline->l_bp->l_fp = bp->b_linep;
  237.         bp->b_linep->l_bp->l_fp = (LINE *)NULL;
  238.         bp->b_linep->l_bp = bp->b_botline->l_bp;
  239.     }
  240.  
  241.     /* let all the proper windows be updated */
  242.     wp = wheadp;
  243.     while (wp) {
  244.         if (wp->w_bufp == bp) {
  245.             wp->w_linep = creg.r_linep;
  246.             wp->w_dotp = creg.r_linep;
  247.             wp->w_doto = 0;
  248.             for (cmark = 0; cmark < NMARKS; cmark++) {
  249.                 wp->w_markp[cmark] = creg.r_linep;
  250.                 wp->w_marko[cmark] = 0;
  251.             }
  252.             wp->w_flag |= (WFHARD|WFMODE);
  253.         }
  254.         wp = wp->w_wndp;
  255.     }
  256.  
  257.     /* and now remember we are narrowed */
  258.     bp->b_flag |= BFNAROW;
  259.     mlwrite(TEXT73);
  260. /*              "[Buffer is narrowed]" */
  261.         return(TRUE);
  262. }
  263.  
  264. /*    widen-from-region (^X->) restores a narrowed region    */
  265.  
  266. PASCAL NEAR widen(f, n)
  267.  
  268. {
  269.     LINE *lp;    /* temp line pointer */
  270.     BUFFER *bp;    /* buffer being narrowed */
  271.     WINDOW *wp;    /* windows to fix up pointers in as well */
  272.  
  273.     /* find the proper buffer and make sure we are narrow */
  274.     bp = curwp->w_bufp;        /* find the right buffer */
  275.     if ((bp->b_flag&BFNAROW) == 0) {
  276.         mlwrite(TEXT74);
  277. /*                      "%%This buffer is not narrowed" */
  278.         return(FALSE);
  279.     }
  280.  
  281.     /* recover the top fragment */
  282.     if (bp->b_topline != (LINE *)NULL) {
  283.         lp = bp->b_topline;
  284.         while (lp->l_fp != (LINE *)NULL)
  285.             lp = lp->l_fp;
  286.         lp->l_fp = bp->b_linep->l_fp;
  287.         lp->l_fp->l_bp = lp;
  288.         bp->b_linep->l_fp = bp->b_topline;
  289.         bp->b_topline->l_bp = bp->b_linep;
  290.         bp->b_topline = (LINE *)NULL;
  291.     }
  292.  
  293.     /* recover the bottom fragment */
  294.     if (bp->b_botline != (LINE *)NULL) {
  295.         lp = bp->b_botline;
  296.         while (lp->l_fp != (LINE *)NULL)
  297.             lp = lp->l_fp;
  298.         lp->l_fp = bp->b_linep;
  299.         bp->b_linep->l_bp->l_fp = bp->b_botline;
  300.         bp->b_botline->l_bp = bp->b_linep->l_bp;
  301.         bp->b_linep->l_bp = lp;
  302.         bp->b_botline = (LINE *)NULL;
  303.     }
  304.  
  305.     /* let all the proper windows be updated */
  306.     wp = wheadp;
  307.     while (wp) {
  308.         if (wp->w_bufp == bp)
  309.             wp->w_flag |= (WFHARD|WFMODE);
  310.         wp = wp->w_wndp;
  311.     }
  312.     /* and now remember we are not narrowed */
  313.     bp->b_flag &= (~BFNAROW);
  314.     mlwrite(TEXT75);
  315. /*              "[Buffer is widened]" */
  316.         return(TRUE);
  317. }
  318.  
  319. /*
  320.  * This routine figures out the bounds of the region in the current
  321.  * window, and fills in the fields of the "REGION" structure pointed to by
  322.  * "rp". Because the dot and mark are usually very close together, we scan
  323.  * outward from dot looking for mark. This should save time. Return a
  324.  * standard code. Callers of this routine should be prepared to get an
  325.  * "ABORT" status; we might make this have the confirm thing later.
  326.  */
  327.  
  328. PASCAL NEAR getregion(rp)
  329.  
  330. register REGION *rp;
  331.  
  332. {
  333.         register LINE   *flp;
  334.         register LINE   *blp;
  335.         long fsize;
  336.         long bsize;
  337.  
  338.         if (curwp->w_markp[0] == (LINE *)NULL) {
  339.                 mlwrite(TEXT76);
  340. /*                      "No mark set in this window" */
  341.                 return(FALSE);
  342.         }
  343.         if (curwp->w_dotp == curwp->w_markp[0]) {
  344.                 rp->r_linep = curwp->w_dotp;
  345.                 if (curwp->w_doto < curwp->w_marko[0]) {
  346.                         rp->r_offset = curwp->w_doto;
  347.                         rp->r_size = (long)(curwp->w_marko[0]-curwp->w_doto);
  348.                 } else {
  349.                         rp->r_offset = curwp->w_marko[0];
  350.                         rp->r_size = (long)(curwp->w_doto-curwp->w_marko[0]);
  351.                 }
  352.                 return(TRUE);
  353.         }
  354.         blp = curwp->w_dotp;
  355.         bsize = (long)curwp->w_doto;
  356.         flp = curwp->w_dotp;
  357.         fsize = (long)(llength(flp)-curwp->w_doto+1);
  358.         while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
  359.                 if (flp != curbp->b_linep) {
  360.                         flp = lforw(flp);
  361.                         if (flp == curwp->w_markp[0]) {
  362.                                 rp->r_linep = curwp->w_dotp;
  363.                                 rp->r_offset = curwp->w_doto;
  364.                                 rp->r_size = fsize+curwp->w_marko[0];
  365.                                 return(TRUE);
  366.                         }
  367.                         fsize += llength(flp)+1;
  368.                 }
  369.                 if (lback(blp) != curbp->b_linep) {
  370.                         blp = lback(blp);
  371.                         bsize += llength(blp)+1;
  372.                         if (blp == curwp->w_markp[0]) {
  373.                                 rp->r_linep = blp;
  374.                                 rp->r_offset = curwp->w_marko[0];
  375.                                 rp->r_size = bsize - curwp->w_marko[0];
  376.                                 return(TRUE);
  377.                         }
  378.                 }
  379.         }
  380.         mlwrite(TEXT77);
  381. /*              "Bug: lost mark" */
  382.         return(FALSE);
  383. }
  384.  
  385. char *PASCAL NEAR getreg()    /* return some of the contents of the current region */
  386.  
  387. {
  388.     register char * sp;    /* ptr into temporary buffer */
  389.     register LINE *linep;
  390.     register int loffs;
  391.     register int s;
  392.     REGION region;
  393.     char value[NSTRING];    /* temp buffer for value */
  394.  
  395.     /* get the region limits */
  396.     if ((s=getregion(®ion)) != TRUE)
  397.         return(errorm);
  398.     linep = region.r_linep;         /* Current line.    */
  399.     loffs = region.r_offset;        /* Current offset.    */
  400.  
  401.     /* don't let the region be larger than a string can hold */
  402.     if (region.r_size >= NSTRING)
  403.         region.r_size = NSTRING - 1;
  404.  
  405.     /* scan the region, record the characters */
  406.     sp = value;
  407.     while (region.r_size--) {
  408.         if (loffs == llength(linep)) {    /* End of line.     */
  409.             *sp++ = '\r';
  410.             linep = lforw(linep);
  411.             loffs = 0;
  412.         } else {            /* Middle of line.    */
  413.             *sp++ = lgetc(linep, loffs);
  414.             ++loffs;
  415.         }
  416.     }
  417.  
  418.     /* and return the constructed value */
  419.     *sp = 0;
  420.     return(value);
  421. }
  422.  
  423.